package inl.resilienceManager.qmul.gemom;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/** COPYRIGHT DISCLAIMER
 * Synopsis: All the source codes presented in this document are intellectual
 * properties of Queen Mary, University of London.
 * 
 * @year 2010
 * @author Peng Jiang, John Bigham, Jiayi Wu Jinfu Wang------------QMUL
 * @version 1.0 
 * */


public class LogFileReader {
	
    private BufferedReader br;

    private boolean hasNext = true;

    private char separator;
    
    private int skipLines;

    private boolean linesSkiped;

    /** The default separator to use if none is supplied to the constructor. */
    public static final char DEFAULT_SEPARATOR = '\t';
 
    /**
     * The default line to start reading.
     */
    public static final int DEFAULT_SKIP_LINES = 0;
    
    private String[] nss = null;
  
    /**
     * Constructs CSVReader with supplied separator and quote char.
     * 
     * @param reader
     *            the reader to an underlying CSV source.
     * @param separator
     *            the delimiter to use for separating entries
     * @param quotechar
     *            the character to use for quoted elements
     * @param line
     *            the line number to skip for start reading 
     */
    public LogFileReader(FileReader reader, char separator, int line) {
        this.br = new BufferedReader(reader);
        this.separator = separator; 
        this.skipLines = line;
    }

    /**
     * Reads the entire file into a List with each element being a String[] of
     * tokens.
     * 
     * @return a List of String[], with each String[] representing a line of the
     *         file.
     * 
     * @throws IOException
     *             if bad things happen during the read
     */
    public double[][] readAll() throws IOException {

        ArrayList<String[]> allElements = new ArrayList<String[]>();
        while (hasNext) {
            String[] nextLineAsTokens = readNext();
            if (nextLineAsTokens != null)
                allElements.add(nextLineAsTokens);
        }
        
        // get the size of the data read, and put them into a 2D array, the length of the 
        // array is the length of observation data, the number variable corresponds to
        // number of items observed
        
        // note the first column is reserved for ID of namespace, and is not a message rate
        // that needs to be recorded
        int length = allElements.size()-1;
        // note the first column is reserved for index nunmbers, and is not a message rate
        // that needs to be recorded
        int number = allElements.get(0).length-1;
        
        double[][] series = new double[length][number];
        
        // retireve column names = namespace ID
        nss = new String[number];
        String[] nsNameRow = allElements.get(0);
        
       	for(int i = 1; i < number+1; i++){
    		nss[i-1] = nsNameRow[i];
    	}
        
     // avoid the first row which is the ID of namespace
        for(int i = 1; i < allElements.size(); i++){
        	String[] row = allElements.get(i);
   
        	// avoid the first column which is the index of data
        	for(int j = 1; j < row.length; j++){
        		series[i-1][j-1] = Double.parseDouble(row[j]);
        	}
        }
         
        return series; 
    }
    
    // return the name of namespaces in a String array, the order in the array corresponds
    // to the order of data in log files
    public String[] readNsName(){
    	return nss;
    }

    /**
     * Reads the next line from the buffer and converts to a string array.
     * 
     * @return a string array with each comma-separated element as a separate
     *         entry.
     * 
     * @throws IOException
     *             if bad things happen during the read
     */
    public String[] readNext() throws IOException {

        String nextLine = getNextLine();
        return hasNext ? parseLine(nextLine) : null;
    }

    /**
     * Reads the next line from the file.
     * 
     * @return the next line from the file without trailing newline
     * @throws IOException
     *             if bad things happen during the read
     */
    private String getNextLine() throws IOException {
    	if (!this.linesSkiped) {
            for (int i = 0; i < skipLines; i++) {
                br.readLine();
            }
            this.linesSkiped = true;
        }
        String nextLine = br.readLine();
        if (nextLine == null) {
            hasNext = false;
        }
        return hasNext ? nextLine : null;
    }

    /**
     * Parses an incoming String and returns an array of elements.
     * 
     * @param nextLine the string to parse 
     * @throws IOException if bad things happen during the read
     */
    private String[] parseLine(String nextLine) throws IOException {

    	String newSeparator = " ";
    	
        if (nextLine == null) {
            return null;
        }
         
        StringBuffer sb = new StringBuffer(); 
     
        for (int i = 0; i < nextLine.length(); i++) {

            char c = nextLine.charAt(i);
            if (c!= separator) { 
            	sb.append(c);
                	  
            }else{
                sb.append(newSeparator);  
            }
            
        }
                 
        return  sb.toString().split(newSeparator);

    }

    /**
     * Closes the underlying reader.
     * 
     * @throws IOException if the close fails
     */
    public void close() throws IOException{
    	br.close();
    }

}
